#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
AI营销方案生成系统 - 工具函数模块
功能：提供常用的工具函数和辅助方法
作者：AI营销系统开发团队
创建时间：2024
"""

from typing import Dict, Any, Optional, List, Union
from datetime import datetime, timezone
from bson import ObjectId
import re
import hashlib
import uuid
import json
import logging


def validate_object_id(obj_id: str) -> bool:
    """
    验证ObjectId格式是否有效
    
    Args:
        obj_id: 要验证的ID字符串
        
    Returns:
        bool: 是否为有效的ObjectId格式
    """
    if not obj_id or not isinstance(obj_id, str):
        return False
    return ObjectId.is_valid(obj_id)


def convert_object_id(doc: Dict[str, Any]) -> Dict[str, Any]:
    """
    将MongoDB文档中的ObjectId转换为字符串
    
    Args:
        doc: MongoDB文档
        
    Returns:
        Dict[str, Any]: 转换后的文档
    """
    if not doc:
        return doc
    
    if '_id' in doc:
        doc['id'] = str(doc['_id'])
        del doc['_id']
    
    return doc


def convert_object_ids(docs: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
    """
    批量转换MongoDB文档中的ObjectId
    
    Args:
        docs: MongoDB文档列表
        
    Returns:
        List[Dict[str, Any]]: 转换后的文档列表
    """
    return [convert_object_id(doc) for doc in docs]


def validate_email(email: str) -> bool:
    """
    验证邮箱格式
    
    Args:
        email: 邮箱地址
        
    Returns:
        bool: 是否为有效邮箱格式
    """
    if not email or not isinstance(email, str):
        return False
    
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return re.match(pattern, email) is not None


def validate_phone(phone: str) -> bool:
    """
    验证手机号格式（中国大陆）
    
    Args:
        phone: 手机号
        
    Returns:
        bool: 是否为有效手机号格式
    """
    if not phone or not isinstance(phone, str):
        return False
    
    # 移除所有非数字字符
    phone_digits = re.sub(r'\D', '', phone)
    
    # 中国大陆手机号格式：11位数字，以1开头
    pattern = r'^1[3-9]\d{9}$'
    return re.match(pattern, phone_digits) is not None


def sanitize_string(text: str, max_length: int = None) -> str:
    """
    清理和验证字符串输入
    
    Args:
        text: 输入文本
        max_length: 最大长度限制
        
    Returns:
        str: 清理后的文本
    """
    if not text or not isinstance(text, str):
        return ''
    
    # 去除首尾空白字符
    text = text.strip()
    
    # 长度限制
    if max_length and len(text) > max_length:
        text = text[:max_length]
    
    return text


def generate_unique_id() -> str:
    """
    生成唯一ID
    
    Returns:
        str: 唯一ID字符串
    """
    return str(uuid.uuid4())


def generate_hash(text: str, algorithm: str = 'md5') -> str:
    """
    生成文本哈希值
    
    Args:
        text: 输入文本
        algorithm: 哈希算法（md5, sha1, sha256）
        
    Returns:
        str: 哈希值
    """
    if not text:
        return ''
    
    text_bytes = text.encode('utf-8')
    
    if algorithm == 'md5':
        return hashlib.md5(text_bytes).hexdigest()
    elif algorithm == 'sha1':
        return hashlib.sha1(text_bytes).hexdigest()
    elif algorithm == 'sha256':
        return hashlib.sha256(text_bytes).hexdigest()
    else:
        raise ValueError(f"不支持的哈希算法: {algorithm}")


def format_datetime(dt: datetime, format_str: str = '%Y-%m-%d %H:%M:%S') -> str:
    """
    格式化日期时间
    
    Args:
        dt: 日期时间对象
        format_str: 格式字符串
        
    Returns:
        str: 格式化后的日期时间字符串
    """
    if not dt:
        return ''
    
    return dt.strftime(format_str)


def parse_datetime(dt_str: str, format_str: str = '%Y-%m-%d %H:%M:%S') -> Optional[datetime]:
    """
    解析日期时间字符串
    
    Args:
        dt_str: 日期时间字符串
        format_str: 格式字符串
        
    Returns:
        Optional[datetime]: 解析后的日期时间对象
    """
    if not dt_str:
        return None
    
    try:
        return datetime.strptime(dt_str, format_str)
    except ValueError:
        return None


def get_utc_now() -> datetime:
    """
    获取当前UTC时间
    
    Returns:
        datetime: 当前UTC时间
    """
    return datetime.utcnow()


def paginate_query(
    collection,
    filter_dict: Dict[str, Any] = None,
    page: int = 1,
    limit: int = 20,
    sort_field: str = 'created_at',
    sort_direction: int = -1
) -> Dict[str, Any]:
    """
    分页查询辅助函数
    
    Args:
        collection: MongoDB集合对象
        filter_dict: 查询过滤条件
        page: 页码（从1开始）
        limit: 每页数量
        sort_field: 排序字段
        sort_direction: 排序方向（1为升序，-1为降序）
        
    Returns:
        Dict[str, Any]: 分页查询结果
    """
    if not filter_dict:
        filter_dict = {}
    
    # 验证分页参数
    if page < 1:
        page = 1
    if limit < 1 or limit > 100:
        limit = 20
    
    # 计算跳过的文档数
    skip = (page - 1) * limit
    
    # 获取总数
    total = collection.count_documents(filter_dict)
    
    # 查询数据
    cursor = collection.find(filter_dict).sort(sort_field, sort_direction).skip(skip).limit(limit)
    items = list(cursor)
    
    # 转换ObjectId
    items = convert_object_ids(items)
    
    # 计算总页数
    total_pages = (total + limit - 1) // limit
    
    return {
        'items': items,
        'total': total,
        'page': page,
        'limit': limit,
        'total_pages': total_pages,
        'has_next': page < total_pages,
        'has_prev': page > 1
    }


def validate_pagination_params(page: Any, limit: Any) -> tuple[int, int]:
    """
    验证和标准化分页参数
    
    Args:
        page: 页码参数
        limit: 每页数量参数
        
    Returns:
        tuple[int, int]: 标准化后的页码和每页数量
    """
    # 验证页码
    try:
        page = int(page) if page else 1
        if page < 1:
            page = 1
    except (ValueError, TypeError):
        page = 1
    
    # 验证每页数量
    try:
        limit = int(limit) if limit else 20
        if limit < 1:
            limit = 20
        elif limit > 100:
            limit = 100
    except (ValueError, TypeError):
        limit = 20
    
    return page, limit


def build_response(
    success: bool = True,
    message: str = '',
    data: Any = None,
    error_code: str = None
) -> Dict[str, Any]:
    """
    构建标准API响应格式
    
    Args:
        success: 是否成功
        message: 响应消息
        data: 响应数据
        error_code: 错误代码
        
    Returns:
        Dict[str, Any]: 标准响应格式
    """
    response = {
        'success': success,
        'message': message,
        'timestamp': get_utc_now().isoformat()
    }
    
    if data is not None:
        response['data'] = data
    
    if error_code:
        response['error_code'] = error_code
    
    return response


def log_request(
    method: str,
    endpoint: str,
    params: Dict[str, Any] = None,
    user_id: str = None
) -> None:
    """
    记录API请求日志
    
    Args:
        method: HTTP方法
        endpoint: API端点
        params: 请求参数
        user_id: 用户ID
    """
    log_data = {
        'method': method,
        'endpoint': endpoint,
        'timestamp': get_utc_now().isoformat()
    }
    
    if params:
        log_data['params'] = params
    
    if user_id:
        log_data['user_id'] = user_id
    
    logging.info(f"API请求: {json.dumps(log_data, ensure_ascii=False)}")


def safe_json_loads(json_str: str, default: Any = None) -> Any:
    """
    安全的JSON解析
    
    Args:
        json_str: JSON字符串
        default: 解析失败时的默认值
        
    Returns:
        Any: 解析结果或默认值
    """
    if not json_str:
        return default
    
    try:
        return json.loads(json_str)
    except (json.JSONDecodeError, TypeError):
        return default


def safe_json_dumps(obj: Any, default: str = '{}') -> str:
    """
    安全的JSON序列化
    
    Args:
        obj: 要序列化的对象
        default: 序列化失败时的默认值
        
    Returns:
        str: JSON字符串或默认值
    """
    try:
        return json.dumps(obj, ensure_ascii=False, default=str)
    except (TypeError, ValueError):
        return default


def truncate_text(text: str, max_length: int = 100, suffix: str = '...') -> str:
    """
    截断文本
    
    Args:
        text: 输入文本
        max_length: 最大长度
        suffix: 截断后缀
        
    Returns:
        str: 截断后的文本
    """
    if not text or len(text) <= max_length:
        return text
    
    return text[:max_length - len(suffix)] + suffix


def extract_keywords(text: str, max_keywords: int = 10) -> List[str]:
    """
    从文本中提取关键词（简单实现）
    
    Args:
        text: 输入文本
        max_keywords: 最大关键词数量
        
    Returns:
        List[str]: 关键词列表
    """
    if not text:
        return []
    
    # 简单的关键词提取：去除标点符号，按空格分割，去重
    import string
    
    # 移除标点符号
    translator = str.maketrans('', '', string.punctuation)
    clean_text = text.translate(translator)
    
    # 分割单词并去重
    words = list(set(clean_text.lower().split()))
    
    # 过滤短词
    keywords = [word for word in words if len(word) > 2]
    
    # 返回指定数量的关键词
    return keywords[:max_keywords]


def calculate_similarity(text1: str, text2: str) -> float:
    """
    计算两个文本的相似度（简单实现）
    
    Args:
        text1: 文本1
        text2: 文本2
        
    Returns:
        float: 相似度（0-1之间）
    """
    if not text1 or not text2:
        return 0.0
    
    # 提取关键词
    keywords1 = set(extract_keywords(text1))
    keywords2 = set(extract_keywords(text2))
    
    if not keywords1 or not keywords2:
        return 0.0
    
    # 计算交集和并集
    intersection = keywords1.intersection(keywords2)
    union = keywords1.union(keywords2)
    
    # 计算Jaccard相似度
    return len(intersection) / len(union) if union else 0.0